package com.yss.datamiddle.Interceptor;

import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.http.MimeHeaders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.*;
import org.springframework.util.CollectionUtils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Field;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 实现 Handlerlnterceptor接口,覆盖其对应的方法即完成了拦截器的开发
 * @author flj
 */
@Slf4j
public class AuthInterceptor implements HandlerInterceptor {
    private final static String URL = "http://119.3.233.217:21000/j_spring_security_check";
    private RestTemplate rest = new RestTemplate();
    @Autowired
    private RedisTemplate redisTemplate;
    /**
     * preHandle在执行Controller之前执行
     * 返回true：继续执行处理器逻辑，包含Controller的功能
     * 返回false：中断请求
     * <p>
     * 处理器执行前方法
     */
    @Override
    public boolean preHandle(
            HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        log.info("初始atlas用户登录");
        String uri = request.getRequestURI();
        System.out.println(uri);
        Object cookie = redisTemplate.opsForValue().get("Cookie");
        if (Objects.isNull(cookie)){
            postForCookie(request);
        } else {
            reflectSetHeader(request,"Cookie",cookie.toString());
            redisTemplate.expire("Cookie", 60*50, TimeUnit.SECONDS);
        }
        return true;
    }

    /**
     * postHandle在请求执行完之后 渲染ModelAndView返回之前执行
     * <p>
     * 处理器处理后方法
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                           ModelAndView modelAndView) throws Exception {
    }

    /**
     * afterCompletion在整个请求执行完毕后执行,无论是否发生异常都会执行
     * <p>
     * 处理器完成后方法
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }


    private void postForCookie(HttpServletRequest request) {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
        params.put("j_username", Collections.singletonList("admin"));
        params.put("j_password", Collections.singletonList("admin"));
        HttpEntity<MultiValueMap<String, String>> requestEntity =
                new HttpEntity<>(params, headers);
        HttpEntity<Map> resp =
                rest.exchange(URL, HttpMethod.POST, requestEntity, Map.class);
        List<String> headerList = resp.getHeaders().get("Set-Cookie");
        if (!CollectionUtils.isEmpty(headerList)) {
            String cookieStr = headerList.get(0);
            List<String> atlassessionids =
                    Arrays.stream(cookieStr.split(";"))
                    .filter(str -> str.indexOf("ATLASSESSIONID") >= 0)
                    .collect(Collectors.toList());
            redisTemplate.opsForValue().set("Cookie", atlassessionids.get(0), 60*50, TimeUnit.SECONDS);
            reflectSetHeader(request,"Cookie",atlassessionids.get(0));
        } else {
            log.info("atlas获取cookie失败");
        }

    }

    /**
     * 修改请求头信息
     * @param request
     */

    private static void reflectSetHeader(HttpServletRequest request, String key, String value){
            Class<? extends HttpServletRequest> requestClass = request.getClass();
            try {
                Field[] declaredFields = requestClass.getDeclaredFields();
                List<Field> list = Arrays.stream(declaredFields).filter((field) -> field.getName().equals("request")).collect(Collectors.toList());
                if (!CollectionUtils.isEmpty(list)) {
                    Field requestField = requestClass.getDeclaredField("request");
                    requestField.setAccessible(true);
                    Object requestObj = requestField.get(request);
                    Field coyoteRequestField = requestObj.getClass().getDeclaredField("coyoteRequest");
                    coyoteRequestField.setAccessible(true);
                    Object coyoteRequestObj = coyoteRequestField.get(requestObj);
                    Field headersField = coyoteRequestObj.getClass().getDeclaredField("headers");
                    headersField.setAccessible(true);
                    MimeHeaders headersObj = (MimeHeaders)headersField.get(coyoteRequestObj);
                    headersObj.removeHeader(key);
                    headersObj.addValue(key).setString(value);
                } else {
                    log.error("请求资源不存在");
                }

            } catch (Exception e) {
                log.error("reflect set header {} error {}", key, e);
            }
    }
}

